//------------------------------------------------------------
//  Filename: x310_fc16_tx.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2024-04-11 19:10
//  Description: 
//   
//  Copyright (C) 2021, UCCHIP, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module x310_fc16_tx #( parameter TCLK_DIV = 199 )
( 
    input  bus_clk,
    input  bus_rst,

    input  [63:0] tx_tdata, input  tx_tlast, input  [3:0] tx_tuser, input  tx_tvalid, output tx_tready,
    output [63:0] rx_tdata, output rx_tlast, output [3:0] rx_tuser, output rx_tvalid, input  rx_tready,

    input  dbg_tag_tx,
    output dbg_tag_tx_dly
);      

///////////////////////////////////////////////////////////////////////
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ wire[63:0] eth_data;
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ wire       eth_data_v;
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ wire       eth_sof;

/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ reg[1:0]   mag_data;
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ reg        mag_data_vld;
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ wire[1:0]  mag_2m_sout;
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ wire       mag_2m_rdy;

///////////////////////////////////////////////////////////////////////
reg        eof;
wire       sof;
wire       eth_eof;
wire[15:0] mag0, mag1;
wire       txd_en;
reg        tx_clear;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    eof <= 1'b0;
  end
  else if(tx_tvalid&tx_tready)begin
    eof <= tx_tlast;
  end
end

assign sof        = tx_tvalid & tx_tready & eof;
assign eth_sof    = sof;
assign eth_data   = tx_tdata;
assign eth_data_v = tx_tvalid & tx_tready;
assign eth_eof    = tx_tvalid & tx_tready & tx_tlast;

reg [2:0]  vef_state;

localparam VEF_IDLE    = 3'd0;
localparam VEF_TIME    = 3'd1;
localparam VEF_PAYLOAD = 3'd2;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    vef_state <= VEF_IDLE;
  end
  else if(eth_eof) begin
    vef_state <= VEF_IDLE;
  end
  else begin
    case(vef_state)
      VEF_IDLE : begin
        if(eth_sof) begin
          if(eth_data[63:61] == 3'b001) vef_state <= VEF_TIME;
          else if (eth_data[63:61] == 3'b000) vef_state <= VEF_PAYLOAD;
        end
      end
      VEF_TIME : begin
        if(eth_data_v) begin
          vef_state <= VEF_PAYLOAD;
        end
      end
      VEF_PAYLOAD : begin
        vef_state <= VEF_PAYLOAD;
      end
      default : begin
        vef_state <= VEF_IDLE;
      end
    endcase // case (vef_state)
  end
end
///////////////////////////////////////////////////////////////////////
reg[7:0]  cntr_div;
wire[7:0] div_parm = TCLK_DIV;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    cntr_div <= 8'b0;
  end
  else begin
    cntr_div <= (cntr_div < div_parm) ? (cntr_div + 1) : 8'b0 ;
  end
end

assign txd_en = ( vef_state == VEF_PAYLOAD ) ? ( eth_data_v ) : 'b0;
///////////////////////////////////////////////////////////////////////

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    mag_data <= 2'b0;
  end
  else if((cntr_div == div_parm[7:2] )||(cntr_div == (div_parm[7:1] + div_parm[7:2] ))) begin
    mag_data <= {mag_data[0],dbg_tag_tx};
  end
end
///////////////////////////////////////////////////////////////////////
always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    mag_data_vld <= 1'b0;
  end
  else begin
    mag_data_vld <= (cntr_div == (div_parm[7:1] + div_parm[7:2] ));
  end
end
///////////////////////////////////////////////////////////////////////
always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    tx_clear <= 1'b0;
  end
  else begin
    tx_clear <= eth_sof;
  end
end

///////////////////////////////////////////////////////////////////////
fifo_ampl_8192x2 
mag_fifo_inst0
(
  .clk      ( bus_clk        ),
  .srst     ( bus_rst|tx_clear ),

  .din      ( mag_data       ),
  .wr_en    ( mag_data_vld   ),

  .dout     ( mag_2m_sout    ),
  .rd_en    ( mag_2m_rdy     ),
  .empty    (                )
);


wire [68:0] ax_tdata; 
wire        ax_tvalid; 
wire        ax_tready;

wire [68:0] bx_tdata; 
wire        bx_tvalid; 
wire        bx_tready;

wire [63:0] cx_tdata; 
wire        cx_tlast; 
wire [3:0]  cx_tuser; 
wire        cx_tvalid; 
wire        cx_tready;

assign dbg_tag_tx_dly = 1'b0;
assign mag_2m_rdy     = txd_en ;

assign mag0      = mag_2m_sout[0] ? 16'h2000 : 16'h0008;
assign mag1      = mag_2m_sout[1] ? 16'h2000 : 16'h0008;

assign ax_tdata  = txd_en ? {tx_tlast, tx_tuser, mag1,mag1,mag0,mag0}: {tx_tlast, tx_tuser, tx_tdata }  ;
assign ax_tvalid = tx_tvalid;
assign tx_tready = ax_tready;

axi_fifo #( .WIDTH ( 69 ) , .SIZE (1) )
axi_fifo_ins0
(
   .clk      ( bus_clk        ),
   .reset    ( bus_rst        ),
   .clear    ( 1'b0           ),

   .i_tdata  ( ax_tdata       ),
   .i_tvalid ( ax_tvalid      ),
   .i_tready ( ax_tready      ),

   .o_tdata  ( bx_tdata       ),
   .o_tvalid ( bx_tvalid      ),
   .o_tready ( bx_tready      )
);

assign {cx_tlast, cx_tuser, cx_tdata} = bx_tdata;
assign cx_tvalid = bx_tvalid;
assign bx_tready = cx_tready;

assign rx_tdata  = cx_tdata  ;
assign rx_tuser  = cx_tuser  ;
assign rx_tlast  = cx_tlast  ; 
assign rx_tvalid = cx_tvalid ; 
assign cx_tready = rx_tready ;

endmodule

